/*
 * brown.c
 *
 *  Created on: Dec 14, 2012
 *      Author: andrey
 */

#include "st7735_spi_stm32.h"

#include "stdint.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_spi.h"
#include "my_lib.h"

//#define LCD_PORT_BKL GPIOA
//#define GPIO_PIN_BKL GPIO_Pin_1

#define LCD_PORT GPIOA
#define GPIO_PIN_RST PAL_PORT_BIT(GPIO_Pin_RST)
#define GPIO_PIN_SCE PAL_PORT_BIT(GPIO_Pin_DC)
#define GPIO_PIN_DC PAL_PORT_BIT(GPIO_Pin_DC)

#define LOW 0
#define HIGH 1

#define LCD_C LOW
#define LCD_D HIGH

#define ST7735_CASET 0x2A
#define ST7735_RASET 0x2B
#define ST7735_MADCTL 0x36
#define ST7735_RAMWR 0x2C
#define ST7735_RAMRD 0x2E
#define ST7735_COLMOD 0x3A

#define MADCTLGRAPHICS 0x6

#define ST7735_width 128
#define ST7735_height 160

#define MADVAL(x) (((x) << 5) | 8)
static uint8_t madctlcurrent = MADVAL(MADCTLGRAPHICS);

struct ST7735_cmdBuf {
  uint8_t command; // ST7735 command byte
  uint8_t delay; // ms delay after
  uint8_t len; // length of parameter data
  uint8_t data[16]; // parameter data
};

static const struct ST7735_cmdBuf initializers[] = {
  // SWRESET Software reset
  { 0x01, 150, 0, 0},
  // SLPOUT Leave sleep mode
  { 0x11, 150, 0, 0},
  // FRMCTR1, FRMCTR2 Frame Rate configuration -- Normal mode, idle
  // frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D)
  { 0xB1, 0, 3, { 0x01, 0x2C, 0x2D }},
  { 0xB2, 0, 3, { 0x01, 0x2C, 0x2D }},
  // FRMCTR3 Frame Rate configureation -- partial mode
  { 0xB3, 0, 6, { 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D }},
  // INVCTR Display inversion (no inversion)
  { 0xB4, 0, 1, { 0x07 }},
  // PWCTR1 Power control -4.6V, Auto mode
  { 0xC0, 0, 3, { 0xA2, 0x02, 0x84}},
  // PWCTR2 Power control VGH25 2.4C, VGSEL -10, VGH = 3 * AVDD
  { 0xC1, 0, 1, { 0xC5}},
  // PWCTR3 Power control, opamp current smal, boost frequency
  { 0xC2, 0, 2, { 0x0A, 0x00 }},
  // PWCTR4 Power control, BLK/2, opamp current small and medium low
  { 0xC3, 0, 2, { 0x8A, 0x2A}},
  // PWRCTR5, VMCTR1 Power control
  { 0xC4, 0, 2, { 0x8A, 0xEE}},
  { 0xC5, 0, 1, { 0x0E }},
  // INVOFF Don't invert display
  { 0x20, 0, 0, 0},
  // Memory access directions. row address/col address, bottom to top refesh (10.1.27)
  { ST7735_MADCTL, 0, 1, {MADVAL(MADCTLGRAPHICS)}},
  // Color mode 16 bit (10.1.30
  { ST7735_COLMOD, 0, 1, {0x05}},
  // Column address set 0..127
  { ST7735_CASET, 0, 4, {0x00, 0x00, 0x00, 0x7F }},
  // Row address set 0..159
  { ST7735_RASET, 0, 4, {0x00, 0x00, 0x00, 0x9F }},
  // GMCTRP1 Gamma correction
  { 0xE0, 0, 16, {0x02, 0x1C, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2D,
0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10 }},
  // GMCTRP2 Gamma Polarity corrction
  { 0xE1, 0, 16, {0x03, 0x1d, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D,
0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10 }},
  // DISPON Display on
  { 0x29, 100, 0, 0},
  // NORON Normal on
  { 0x13, 10, 0, 0},
  // End
  { 0, 0, 0, 0}
};


//void spiInit(SPI_TypeDef *SPIx)
//{
//  SPI_InitTypeDef SPI_InitStructure;
//  GPIO_InitTypeDef GPIO_InitStructure;
//
//  GPIO_StructInit(&GPIO_InitStructure);
//  SPI_StructInit(&SPI_InitStructure);
//
//
//  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
//  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
//  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
//  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
//  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
//  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
//  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
//  SPI_InitStructure.SPI_CRCPolynomial = 7;
//  SPI_Init(SPIx, &SPI_InitStructure);
//
//  SPI_Cmd(SPIx, ENABLE);
//}



int spiReadWrite(SPI_TypeDef* SPIx, uint8_t *rbuf,
         const uint8_t *tbuf, int cnt)
{
  int i;

//  SPIx->CR1 = (SPIx->CR1 & ~SPI_BaudRatePrescaler_256) |
//               speeds[speed];

  for (i = 0; i < cnt; i++){
    if (tbuf) {
      SPI_I2S_SendData(SPIx, *tbuf++);
    } else {
      SPI_I2S_SendData(SPIx, 0xff);
    }
    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
    if (rbuf) {
      *rbuf++ = SPI_I2S_ReceiveData(SPIx);
    } else {
      SPI_I2S_ReceiveData(SPIx);
    }
  }
  return i;
}

static void LcdWrite(char dc, const char *data, int nbytes)
{
  GPIO_WriteBit(LCD_PORT,GPIO_PIN_DC, dc); // dc 1 = data, 0 = control
  GPIO_ResetBits(LCD_PORT,GPIO_PIN_SCE);
  spiReadWrite(SPILCD, 0, data, nbytes);
  GPIO_SetBits(LCD_PORT,GPIO_PIN_SCE);
}

//static void LcdWrite16(char dc, const uint16_t *data, int cnt)
//{
//  GPIO_WriteBit(LCD_PORT,GPIO_PIN_DC, dc); // dc 1 = data, 0 = control
//  GPIO_ResetBits(LCD_PORT,GPIO_PIN_SCE);
//  spiReadWrite16(SPILCD, 0, data, cnt);
//  GPIO_SetBits(LCD_PORT,GPIO_PIN_SCE);
//}

static void ST7735_writeCmd(uint8_t c)
{
  LcdWrite(LCD_C, &c, 1);
}

int zero = 0;

void ST7735_setAddrWindow(uint16_t x0, uint16_t y0,
uint16_t x1, uint16_t y1, uint8_t madctl)
{
  madctl = MADVAL(madctl);
  if (madctl != madctlcurrent){
      ST7735_writeCmd(ST7735_MADCTL);
      LcdWrite(LCD_D, &madctl, 1);
      madctlcurrent = madctl;
  }
  ST7735_writeCmd(ST7735_CASET);
//  LcdWrite(LCD_D, &zero, 1);
  LcdWrite(LCD_D, &x0, 2);

//  LcdWrite(LCD_D, &zero, 1);
  LcdWrite(LCD_D, &x1, 2);

  ST7735_writeCmd(ST7735_RASET);
  LcdWrite(LCD_D, &zero, 1);
  LcdWrite(LCD_D, &y0, 1);

  LcdWrite(LCD_D, &zero, 1);
  LcdWrite(LCD_D, &y1, 1);

  ST7735_writeCmd(ST7735_RAMWR);
}

void ST7735_pushColor(uint16_t *color, int cnt)
{
//	char t = color[0] > 8;
//  LcdWrite(LCD_D, &t, 1);
  LcdWrite(LCD_D, color, 2 * cnt);
}

//void ST7735_backLight(uint8_t on)
//{
//  if (on)
//    GPIO_WriteBit(LCD_PORT_BKL,GPIO_PIN_BKL, LOW);
//  else
//    GPIO_WriteBit(LCD_PORT_BKL,GPIO_PIN_BKL, HIGH);
//}

void drawPixelInt(uint16_t x, uint16_t y, uint16_t color) {
	//setAddrWindow(x, y, x + 1, y + 1);

	ST7735_setAddrWindow(0, 0, 150, 150, MADCTLGRAPHICS);
	//setAddrWindow(0, 0, 100 + 1, 100 + 1);
	ST7735_writeCmd(ST7735_RAMWR);  // write to RAM
//	writedata(color >> 8);
//	writedata(color);
}


void ST7735_init()
{
  GPIO_InitTypeDef GPIO_InitStructure;
  const struct ST7735_cmdBuf *cmd;

  // set up pins and clocks

  initSpiForLcd();

  // set cs, reset low

  GPIO_WriteBit(LCD_PORT,GPIO_PIN_SCE, HIGH);
  GPIO_WriteBit(LCD_PORT,GPIO_PIN_RST, HIGH);
  Delay(10);
  GPIO_WriteBit(LCD_PORT,GPIO_PIN_RST, LOW);
  Delay(10);
  GPIO_WriteBit(LCD_PORT,GPIO_PIN_RST, HIGH);
  Delay(10);

  // Send initialization commands to ST7735

  for (cmd = initializers; cmd->command; cmd++)
    {
      LcdWrite(LCD_C, &(cmd->command), 1);
      if (cmd->len)
        LcdWrite(LCD_D, cmd->data, cmd->len);
      if (cmd->delay)
        Delay(cmd->delay);
    }


//  while(1) {

  ST7735_setAddrWindow(0, 0, ST7735_width - 1, ST7735_height - 1, MADCTLGRAPHICS);

  int a = 546546546;
  for(int i = 0; i< ST7735_width * ST7735_height;i++) {
	  ST7735_pushColor(&a, 2);
  }

//  }

}




